package com.example.controller;

import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.annotation.Log;
import com.example.common.result.Result;
import com.example.entity.dto.FileUpload.FileDeleteDto;
import com.example.entity.dto.FileUpload.FileDownloadDto;
import com.example.entity.dto.FileUpload.FileListDto;
import com.example.entity.yifei.Attach;
import com.example.entity.ymlConfig.YmlConfig;
import com.example.exception.CustomException;
import com.example.mapper.AttachMapper;
import com.example.service.FileService;
import com.example.untils.AESUtil;
import com.example.untils.SecurityUtils;
import com.example.untils.StringUtils;
import com.example.untils.TimeUtils;
import com.github.houbb.opencc4j.util.ZhConverterUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@RestController
@RequestMapping("/api/file")
@Api(tags = "文件上传")
public class FileController {

    private static final String SECRET_KEY = "HZSECRET_KEY123+*/-546841QWERASD";

    @Value("${file.upload-dir}")
    private String uploadDir;

    @Value("${file.upload-dir}")
    private String downloadDir;

    @Autowired
    private AttachMapper attachMapper;

    @Autowired
    private FileService fileService;

//    @Log("EXCEL销售订单")
    @ApiOperation("EXCEL销售订单")
    @PostMapping("getExcels")
    public void getExcels(@RequestPart("files") MultipartFile files[],
                          HttpServletResponse response) throws Exception {
        fileService.getExcels(files, response);
    }

    @Log("文件删除")
    @ApiOperation("文件删除")
    @PostMapping("fileDelete")
    public Result fileDelete(FileDeleteDto fileDeleteDto) {
        String keyValues = new String(fileDeleteDto.getType() + "||" + fileDeleteDto.getId());
        Attach attach = attachMapper.selectOne(new LambdaQueryWrapper<Attach>().eq(Attach::getCompanyid, fileDeleteDto.getCompanyId())
                .eq(Attach::getKeyvalues, keyValues).eq(Attach::getParent, fileDeleteDto.getProgramId())
                .eq(Attach::getDocid, fileDeleteDto.getDocID()));
        if(attach == null) {
            throw new CustomException("500", "文件不存在");
//            return Result.error("文件不存在");
        }
        if(StringUtils.isEmpty(fileDeleteDto.getUserId())) {
            throw new CustomException("500", "用户不能为空");
        }
        if(!attach.getUserid().equals(fileDeleteDto.getUserId())) {
            throw new CustomException("500", "只有文件上传者才可以删除文件");
        }
        attachMapper.delete(new LambdaQueryWrapper<Attach>().eq(Attach::getCompanyid, fileDeleteDto.getCompanyId())
                .eq(Attach::getKeyvalues, keyValues).eq(Attach::getParent, fileDeleteDto.getProgramId())
                .eq(Attach::getDocid, fileDeleteDto.getDocID()).eq(Attach::getUserid, fileDeleteDto.getUserId()));
//        StringBuffer fileDir = new StringBuffer(downloadDir);
//        fileDir.append(attach.getDocid().substring(3, 6)).append("000").append(File.separator)
//                .append(attach.getDocid()).append(File.separator);
//
//        File file = new File(fileDir.toString() + attach.getFilename());
//        if(!file.exists()){
//            throw new CustomException("500", "下载文件不存在");
////            return Result.error("下载文件不存在");
//        }
        return Result.success("删除成功");
    }

    @ApiOperation("文件列表浏览")
    @PostMapping("fileList")
    public Result<List<Attach>> fileList(@RequestBody FileListDto fileListDto) {

        List<Attach> list = fileService.fileList(fileListDto);
        return Result.success(list);
    }

//    @Log("上传文件列表  共享文件夹版")
//    @ApiOperation("上传文件列表  共享文件夹版")
//    @PostMapping("fileUpload")
    // smb://administrator:123@192.168.1.47/imglist/
//    public Result fileUpload(@RequestParam("files") MultipartFile files[],
//                             FileUploadDto dto) {
//        if(StringUtils.isEmpty(dto.getUserId())) {
//            return Result.error("用户不能为空");
//        }
//        if(StringUtils.isEmpty(dto.getType()) || StringUtils.isEmpty(dto.getId())) {
//            return Result.error("单别单号不能为空");
//        }
//
//        Set<String> res = new HashSet<>();
//        String keyValues = new String(dto.getType() + "||" + dto.getId());
//        int idx = Integer.parseInt(attachMapper.generateSeqNo(dto.getProgramId(), keyValues,
//                dto.getCompanyId(), dto.getUserId()));
//        String remoteUrl = uploadDir;
//        String olduploadDir = remoteUrl;
//
//        SmbFile remoteFile = null;
//        InputStream inputStream = null;
//        SmbFileOutputStream outputStream = null;
//        for(MultipartFile file : files) {
//            try
//            {
//                // 检查文件是否为空
//                if (file.isEmpty()) {
//                    return Result.error("文件为空");
//                }
//                // 获取文件名
//                String fileName = file.getOriginalFilename();
//
//                String docId = attachMapper.generateDocId();
//                String addDate = TimeUtils.getNowTime().substring(0, 8);
//                SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
//                // 获取当前时间
//                Date currentDate = new Date();
//                // 格式化日期时间
//                String addTime = sdf.format(currentDate);
//
//                olduploadDir += docId.substring(3, 7) + "000" +
//                        "/" + docId + "/";
////                olduploadDir += docId.substring(3, 6) + "000" +
////                        File.separator + docId + File.separator;
//
//                remoteFile = new SmbFile(olduploadDir);
//                remoteFile.connect();//尝试连接
//                if(!remoteFile.exists()) {
//                    remoteFile.mkdirs();
//                }
//
//                SmbFile targetFile = new SmbFile(olduploadDir + fileName);
//                outputStream = new SmbFileOutputStream(targetFile);
//
//                byte[] buffer = new byte[4096];
//                int bytesRead;
//                inputStream = new BufferedInputStream(file.getInputStream());
//                while ((bytesRead = inputStream.read(buffer)) > 0) {
//                    outputStream.write(buffer, 0, bytesRead);
//                }
//                outputStream.flush();
//
//                Attach attach = new Attach(dto.getProgramId(), keyValues,
//                        dto.getCompanyId(), dto.getUserId(), "1", String.format("%03d", idx),
//                        fileName, docId, "001", addDate, addTime, dto.getKeyFields());
//                attachMapper.insert(attach);
//                // 返回成功信息
//                res.add("文件上传成功: ");
//                idx++;
//                olduploadDir = remoteUrl;
//            } catch (Exception e) {
//                e.printStackTrace();
//                return Result.error("文件上传失败: " + e.getMessage());
//            }
//
//        }
//        if(inputStream != null) {
//            try {
//                inputStream.close();
//            } catch (IOException e) {
//                throw new RuntimeException(e);
//            }
//        }
//        if(outputStream != null) {
//            try {
//                outputStream.close();
//            } catch (IOException e) {
//                throw new RuntimeException(e);
//            }
//        }
//        return Result.success("连接成功");
//    }

    @Log("上传文件列表")
    @ApiOperation("上传文件列表")
    @PostMapping("fileUpload")
    public Result fileUpload(@RequestParam("files") MultipartFile files[]) {
//        if(StringUtils.isEmpty(dto.getUserId())) {
//            return Result.error("用户不能为空");
//        }
//        if(StringUtils.isEmpty(dto.getType()) || StringUtils.isEmpty(dto.getId())) {
//            return Result.error("单别单号不能为空");
//        }
        String username = SecurityUtils.getLoginUser().getUsername();
        if(StringUtils.isEmpty(username)) {
            return Result.error("请先登录");
        }

        String olduploadDir = uploadDir;
        System.out.println("olduploadDir: " + olduploadDir);
//        String res = "";
        Set<String> res = new HashSet<>();
//        String keyValues = new String(dto.getType() + "||" + dto.getId());
//        int idx = Integer.parseInt(attachMapper.generateSeqNo(dto.getProgramId(), keyValues,
//                dto.getCompanyId(), dto.getUserId()));
        for(MultipartFile file : files) {
            try
            {
                // 检查文件是否为空
                if (file.isEmpty()) {
                    return Result.error("文件内容为空,请选择要上传的文件");
                }
                // 获取文件名
                String name = file.getOriginalFilename();

                assert name != null;
                String fileName = changeToSimpleChinese(name);

                String docId = attachMapper.generateDocId();
                System.out.println("docId: " + docId);
                olduploadDir += docId.substring(3, 6) + "000" +
                        File.separator + docId + File.separator;
// picPath = "\\\\192.168.0.208\\DocLibrary\\" + wdbh.Substring(3,4) + "000\\" + wdbh + ".001";
                System.out.println(olduploadDir + File.separator + fileName);
                File dest = new File(olduploadDir + File.separator + fileName);
                if (!dest.getParentFile().exists()) {
                    dest.getParentFile().mkdirs();
                }
                // 在实际应用中，你可以根据需要对文件进行处理，例如保存到磁盘或者数据库中
                file.transferTo(dest);
                AESUtil.encryptFile(olduploadDir + File.separator + fileName);
                // 返回成功信息
                res.add("/files/" + docId.substring(3, 6) + "000" +
                        "/" + docId + "/" + fileName);
                String addDate = TimeUtils.getNowTime().substring(0, 8);
                // 获取当前时间
                Date currentDate = new Date();
                // 格式化日期时间
                SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
                String addTime = sdf.format(currentDate);
                Attach attach = new Attach("1", UUID.fastUUID().toString(),
                        YmlConfig.getYFCOMPANY(), username, "1", "1",
                        fileName, docId, "001", addDate, addTime, "");
                attachMapper.insert(attach);
//                idx++;
                olduploadDir = uploadDir;
            } catch (Exception e) {
                e.printStackTrace();
                return Result.error("文件上传失败: " + e.getMessage());
            }
        }
        return Result.success(res);
    }

    @ApiOperation("下载文件")
    @PostMapping("fileDownLoad")
    public ResponseEntity fileDownLoad(@RequestBody FileDownloadDto fileDownloadDto) throws Exception{

        String keyValues = new String(fileDownloadDto.getType() + "||" + fileDownloadDto.getId());
        Attach attach = attachMapper.selectOne(new LambdaQueryWrapper<Attach>().eq(Attach::getCompanyid, fileDownloadDto.getCompanyId())
                .eq(Attach::getKeyvalues, keyValues).eq(Attach::getParent, fileDownloadDto.getProgramId())
                .eq(Attach::getDocid, fileDownloadDto.getDocID()));
        if(attach == null) {
            throw new CustomException("500", "文件不存在");
//            return Result.error("文件不存在");
        }
        StringBuffer fileDir = new StringBuffer(downloadDir);
        fileDir.append(attach.getDocid().substring(3, 6)).append("000").append(File.separator)
                .append(attach.getDocid()).append(File.separator);

        File file = new File(fileDir.toString() + attach.getFilename());
        if(!file.exists()){
            throw new CustomException("500", "下载文件不存在");
//            return Result.error("下载文件不存在");
        }
        // 构建加密文件路径
        Path encryptedFilePath = Paths.get(fileDir.toString()).resolve(attach.getFilename());

        // 加载加密文件资源
        Resource encryptedResource = new InputStreamResource(new FileInputStream(encryptedFilePath.toFile()));

        // 创建解密流
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(SECRET_KEY.getBytes(), "AES"));
        // 解密文件到临时文件
        File tempFile = File.createTempFile("decrypted_", ".tmp");
        try (InputStream encryptedStream = new FileInputStream(encryptedFilePath.toFile());
             CipherInputStream decryptedStream = new CipherInputStream(encryptedStream, cipher);
             OutputStream outputStream = new FileOutputStream(tempFile)) {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = decryptedStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        }
        // 构建解密后文件的资源对象
        Resource decryptedResource = new InputStreamResource(new FileInputStream(tempFile));
        // 构建响应头部
        HttpHeaders headers = new HttpHeaders();
        headers.setContentLength(tempFile.length());
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.setContentDispositionFormData("attachment", attach.getFilename());
        ResponseEntity<Object> entity = new ResponseEntity<>(decryptedResource, headers, HttpStatus.OK);
        return entity;
    }

    public static String changeToSimpleChinese(String searchName) {
        StringBuilder stringBuilder = new StringBuilder();
        int n = 0;
        for(int i = 0; i < searchName.length(); i++) {
            n = (int)searchName.charAt(i);
            char c = searchName.charAt(i);
            String s = String.valueOf(c);
            if(!(19968 <= n && n <40869)) {
                stringBuilder.append(c);
            }else {
                List<String> strings = ZhConverterUtil.toSimple(c);
                if (strings != null) {
                    int z = 1;
                    //下面用于解决：如果出现简体字转简体居然不是同一个字的时候
                    for (String string : strings) {
                        if (string.equals(s)) {
                            stringBuilder.append(string);
                        } else if (strings.size() == z) {
                            stringBuilder.append(strings.get(0));
                        }
                        z++;
                    }
                } else {
                    stringBuilder.append(c);
                }
            }
        }
        return stringBuilder.toString();
    }
}
